package main

import (
	"fmt"
	"strings"
	"time"

	"gitee.com/filters/utils/logv"
	"github.com/rs/zerolog"
)

// 演示钩子功能的主程序

func main1() {
	fmt.Println("=== logv 钩子功能演示 ===\n")

	// 1. 基本钩子演示
	fmt.Println("1. 基本钩子演示:")
	basicHookDemo()

	// 2. 级别过滤钩子演示
	fmt.Println("\n2. 级别过滤钩子演示:")
	levelHookDemo()

	// 3. 条件钩子演示
	fmt.Println("\n3. 条件钩子演示:")
	conditionalHookDemo()

	// 4. 多个钩子演示
	fmt.Println("\n4. 多个钩子演示:")
	multipleHooksDemo()

	// 5. 实用钩子演示
	fmt.Println("\n5. 实用钩子演示:")
	practicalHooksDemo()

	// 6. 公共字段钩子演示
	fmt.Println("\n6. 公共字段钩子演示:")
	commonFieldsDemo()

	fmt.Println("\n=== 演示结束 ===")
}

func basicHookDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	// 添加基本钩子
	logv.AddHook(logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		e.Str("demo", "basic_hook")
		e.Str("level_name", level.String())
	}))

	logv.Info("这是一条基本的日志消息")
	logv.Error("这是一条错误消息")
}

func levelHookDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	// 只在错误和致命错误级别时添加告警标记
	alertHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		e.Bool("needs_alert", true)
		e.Str("severity", "high")
		e.Str("demo", "level_hook")
	})

	levelHook := logv.NewLevelHook(
		[]zerolog.Level{zerolog.ErrorLevel, zerolog.FatalLevel},
		alertHook,
	)
	logv.AddHook(levelHook)

	logv.Info("普通信息日志 - 不会触发告警钩子")
	logv.Warn("警告日志 - 不会触发告警钩子")
	logv.Error("错误日志 - 会触发告警钩子")
}

func conditionalHookDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	// 只在消息包含数据库相关关键词时添加分类标记
	dbHook := logv.NewConditionalHook(
		func(level zerolog.Level, msg string) bool {
			return strings.Contains(msg, "database") ||
				strings.Contains(msg, "sql") ||
				strings.Contains(msg, "mysql")
		},
		logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
			e.Str("category", "database")
			e.Bool("db_related", true)
			e.Str("demo", "conditional_hook")
		}),
	)
	logv.AddHook(dbHook)

	logv.Info("用户登录成功 - 不会触发数据库钩子")
	logv.Info("database connection established - 会触发数据库钩子")
	logv.Error("sql query timeout - 会触发数据库钩子")
	logv.Warn("内存使用率较高 - 不会触发数据库钩子")
}

func multipleHooksDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	// 添加多个钩子
	// 钩子1: 添加应用信息
	appHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		e.Str("app_name", "demo-service")
		e.Str("version", "1.0.0")
	})

	// 钩子2: 添加自定义时间戳
	timeHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		e.Str("custom_time", time.Now().Format("15:04:05.000"))
	})

	// 钩子3: 统计日志数量
	var logCount int
	countHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		logCount++
		e.Int("log_count", logCount)
		e.Str("demo", "multiple_hooks")
	})

	logv.AddHook(appHook)
	logv.AddHook(timeHook)
	logv.AddHook(countHook)

	logv.Info("第一条日志")
	logv.Warn("第二条日志")
	logv.Error("第三条日志")
}

func practicalHooksDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	// 实用钩子1: 错误统计钩子
	errorCount := 0
	errorCountHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		if level >= zerolog.ErrorLevel {
			errorCount++
			e.Int("total_errors", errorCount)
		}
	})

	// 实用钩子2: 敏感数据检测钩子
	sensitiveWords := []string{"password", "token", "secret", "key"}
	sensitiveHook := logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		for _, word := range sensitiveWords {
			if strings.Contains(strings.ToLower(msg), word) {
				e.Bool("sensitive_data_detected", true)
				e.Str("warning", "message contains sensitive information")
				break
			}
		}
	})

	// 实用钩子3: 性能监控钩子
	performanceHook := logv.NewConditionalHook(
		func(level zerolog.Level, msg string) bool {
			return strings.Contains(msg, "slow") || strings.Contains(msg, "timeout")
		},
		logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
			e.Str("performance_issue", "detected")
			e.Bool("needs_optimization", true)
		}),
	)

	logv.AddHook(errorCountHook)
	logv.AddHook(sensitiveHook)
	logv.AddHook(performanceHook)

	// 演示各种场景
	logv.Info("用户登录成功")
	logv.Warn("API调用较慢，响应时间: 2.5s")       // 触发性能钩子
	logv.Error("数据库连接失败")                 // 触发错误统计钩子
	logv.Info("用户输入了password: 123456")    // 触发敏感数据钩子
	logv.Error("Redis连接超时")               // 触发错误统计钩子
	logv.Warn("检测到slow query，执行时间: 5.2s") // 触发性能钩子
	logv.Error("JWT token验证失败")           // 触发错误统计和敏感数据钩子
}

func commonFieldsDemo() {
	// 清空现有钩子
	logv.ClearHooks()

	fmt.Println("  6.1 设置全局公共字段:")
	// 设置全局公共字段，每个日志都会包含这些字段
	logv.SetCommonFields(map[string]interface{}{
		"app_name":    "e-commerce-service",
		"version":     "2.1.0",
		"environment": "production",
		"region":      "us-east-1",
	})

	logv.Info("服务启动成功")
	logv.Error("数据库连接失败")

	fmt.Println("\n  6.2 动态添加公共字段:")
	// 动态添加单个公共字段
	logv.AddCommonField("instance_id", "i-1234567890abcdef0")
	logv.AddCommonField("deployment_id", "deploy-20231201-001")

	logv.Info("实例信息已更新")
	logv.Warn("内存使用率较高: 85%")

	fmt.Println("\n  6.3 修改公共字段:")
	// 修改现有字段
	logv.AddCommonField("status", "degraded")
	logv.Error("服务进入降级模式")

	// 移除某个字段
	logv.RemoveCommonField("deployment_id")
	logv.Info("部署信息已清理")

	fmt.Println("\n  6.4 查看当前公共字段:")
	fields := logv.GetCommonFields()
	fmt.Printf("  当前公共字段: %+v\n", fields)

	logv.Info("当前配置的公共字段如上所示")

	fmt.Println("\n  6.5 结合其他钩子使用:")
	// 添加其他钩子，与公共字段钩子一起工作
	logv.AddHook(logv.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
		e.Str("request_id", "req-"+generateID())
		e.Str("trace_id", "trace-"+generateID())
	}))

	logv.Info("处理用户请求")
	logv.Error("请求处理失败")

	fmt.Println("\n  6.6 清空公共字段:")
	logv.ClearCommonFields()
	logv.Info("公共字段已清空，此日志不包含之前的公共字段")
}

// generateID 生成示例ID
func generateID() string {
	return fmt.Sprintf("%d", time.Now().UnixNano()%1000000)
}
